
module frv_iu_bru (
    input                       clk             ,
    input                       rst_n           ,
    input                       pd_rst          ,
    // BRU Control                                                  
    // The BRU input interface must delay 1 clock to make the timing right
    input                       bru_req         ,
    input [5:0]     bru_inst_id     , // Instruction ID  
    input                       bru_ctrl_beq    ,
    input                       bru_ctrl_bne    ,
    input                       bru_ctrl_blt    ,
    input                       bru_ctrl_bge    ,
    input                       bru_ctrl_jal    ,
    input                       bru_ctrl_jalr   ,
    //BRU Operation Num                             
    input [31:0]                bru_pc_data     ,
    input [31:0]                bru_op1_val     ,
    input [31:0]                bru_op2_val     ,
    input                       bru_rd_vld      ,
    input [31:0]                bru_imm_val     ,    
    input [31:0]                bru_bp_taddr    , // bp target addr
    input                       bru_bp_taken    , // bp taken
    input [3:0]                 bru_bp_bhtv     , // BHT Entry Value
    input [31:0]                bru_bp_phtv     , // PHT Entry Value    
    //BRU Response                                  
    output  [5:0]   bru_resp_inst_id,
    output                      bru_resp_vld    ,
    output                      bru_resp_taken  ,
    output                      bru_resp_rd_vld ,
    output  [31:0]              bru_resp_rd_val ,
    output  [31:0]              bru_caddr_val   , //correct Address value
    output                      bru_flush           
);
 
wire            eq,ne;
wire [31:0]     target_addr;
wire [31:0]     target_addr_op2;

wire            branch_taken;
wire            ge,lt;
wire            jmp;

wire            br_miss_predict;
wire            br_addr_miss_match;
wire            bru_flush_nxt;

wire [31:0]     jump_ret_addr;

wire            br_exec_en;

wire            bru_resp_rd_vld_nxt;
//BRU Flush Control
wire flush_en;
wire bru_flush_older;

assign br_exec_en = bru_req && ~flush_en;

rob_id_cmpo #(5+1) _bru_rob_id_cmpo(bru_resp_inst_id,bru_inst_id,bru_flush_older);
// //The BRU Pick Result in ISQ is younger than the BRU Resp Instruction whose result is branch prediction error,abandene pick Result 
assign flush_en  = bru_flush_older && bru_flush && bru_req;

assign eq = bru_op1_val == bru_op2_val;
assign ne = ~eq;
assign ge = bru_op1_val >= bru_op2_val;
assign lt = ~ge;

assign jmp = bru_ctrl_jal | bru_ctrl_jalr;

assign branch_taken =  br_exec_en &&
                        ((bru_ctrl_beq & eq) |
						(bru_ctrl_bne & ne) |
						(bru_ctrl_blt & lt) |
						(bru_ctrl_bge & ge) |
						(jmp));

assign target_addr_op2 = bru_ctrl_jalr ? bru_op1_val : bru_pc_data;
assign target_addr     = target_addr_op2 + bru_imm_val;

assign br_addr_miss_match = branch_taken && bru_bp_taken && target_addr != bru_bp_taddr;
assign br_miss_predict = branch_taken != bru_bp_taken || br_addr_miss_match;

assign bru_flush_nxt   = br_exec_en && br_miss_predict;

assign jump_ret_addr   = bru_pc_data + 4;

assign bru_resp_rd_vld_nxt = br_exec_en && bru_rd_vld;

dffr #(.DW(5+1))     bru_resp_inst_id_ff (clk,rst_n,1'b1,bru_inst_id  ,bru_resp_inst_id);
dffr #(.DW(1)              )     bru_resp_vld_ff     (clk,rst_n,1'b1,br_exec_en   ,bru_resp_vld    );
dffr #(.DW(1)              )     bru_resp_taken_ff   (clk,rst_n,1'b1,branch_taken ,bru_resp_taken  );
dffr #(.DW(1)              )     bru_resp_rd_vld_ff  (clk,rst_n,1'b1,bru_resp_rd_vld_nxt ,bru_resp_rd_vld );
dffr #(.DW(32)             )     bru_resp_rd_val_ff  (clk,rst_n,1'b1,jump_ret_addr,bru_resp_rd_val );
dffr #(.DW(32)             )     bru_caddr_val_ff    (clk,rst_n,1'b1,target_addr  ,bru_caddr_val   ); //correct Address value
dffr #(.DW(1)              )     bru_flush_ff        (clk,rst_n,1'b1,bru_flush_nxt,bru_flush       );   

endmodule

